﻿using System;
using System.Collections.Generic;
using OhioState.AssetManaged;

namespace OhioState.Graphics
{
    [Serializable]
    public class CameraSelector : SharedAsset, ICamera
    {
        public CameraSelector(string name, ICamera camera) : base(name)
        {
            cameraList.Add(camera);
            currentCamera = camera;
            IAssetManaged asset = camera as IAssetManaged;
            if (asset != null)
            {
                asset.AddChangedEventHandler(this.FireUpdateChangedEvent);
                asset.AddChangingEventHandler(this.FireUpdateChangedEvent);
            }
        }
        public CameraSelector(ICamera camera) : this(String.Empty, camera )
        {
        }

        public void AddCamera(ICamera camera)
        {
            cameraList.Add(camera);
        }
        public void SelectCamera(string name)
        {
            // Rather than holding a dictionary and separating the name from the camera, 
            // we will do a more expensive search. This allows the camera names to be
            // changed underneath this class without a lot of subscription logic.
            // As this routine should be called rather infrequenty, this is a good
            // trade-off.
            foreach (ICamera camera in cameraList)
            {
                IAssetManaged asset = camera as IAssetManaged;
                if (asset != null && asset.Name == name && camera != currentCamera)
                {
                    IAssetManaged oldAsset = currentCamera as IAssetManaged;
                    oldAsset.RemoveChangedEventHandler(this.FireUpdateChangedEvent);
                    currentCamera = camera;
                    asset.AddChangedEventHandler(this.FireUpdateChangedEvent);
                    asset.AddChangingEventHandler(this.FireUpdateChangedEvent);
                    this.FireUpdateChangingEvent(this);
                    this.FireUpdateChangedEvent(this);
                    return;
                }
            }
        }

        #region ICamera Members
        public float AspectRatio
        {
            get
            {
                return currentCamera.AspectRatio;
            }
            set
            {
                currentCamera.AspectRatio = value;
            }
        }

        public OhioState.Math.Matrix4 GetModelViewMatrix()
        {
            return currentCamera.GetModelViewMatrix();
        }

        public OhioState.Math.Matrix4 GetProjectionMatrix()
        {
            return currentCamera.GetProjectionMatrix();
        }

        public void SetModelViewMatrix(OhioState.Math.Matrix4 matrix)
        {
            currentCamera.SetModelViewMatrix(matrix);
        }

        public void SetProjection(float viewAngle, float aspectRatio, float near, float far)
        {
            currentCamera.SetProjection(viewAngle,aspectRatio,near,far);
        }

        public void SetProjection(float left, float right, float bottom, float top, float near, float far)
        {
            currentCamera.SetProjection(left, right, bottom, top, near, far);
        }

        public void SetProjectionMatrix(OhioState.Math.Matrix4 matrix)
        {
            currentCamera.SetProjectionMatrix(matrix);
        }
        #endregion

        #region ITransform Members
        public OhioState.Math.Vector3 RotationCenter
        {
            get
            {
                return currentCamera.RotationCenter;
            }
            set
            {
                currentCamera.RotationCenter = value;
            }
        }

        public void Rotate(float radians, OhioState.Math.Vector3 axis)
        {
            currentCamera.Rotate(radians, axis);
        }

        public void Translate(float x, float y, float z)
        {
            currentCamera.Translate(x, y, z);
        }

        public void Translate(OhioState.Math.Vector3 translate)
        {
            currentCamera.Translate(translate);
        }

        public void Scale(float scaleX, float scaleY, float scaleZ)
        {
            currentCamera.Scale(scaleX, scaleY, scaleZ);
        }
        #endregion

        #region IZoomLens Members
        public void ZoomLens(float zoom)
        {
            currentCamera.ZoomLens(zoom);
        }
        #endregion

        #region File operations
        public override void ReaquireAssets()
        {
            //
            // Use the Properties to ensure the old event handlers are removed and new
            //    ones are added. Particularly if we are setting an item to itself.
            //
            List<ICamera> newCameraList = new List<ICamera>();
            foreach (ICamera camera in cameraList)
            {
                IAssetManaged cameraAsset = camera as IAssetManaged;
                IAssetManaged item = AssetManager.Instance.Find(cameraAsset.GetType(), cameraAsset.Name);
                newCameraList.Add(item as ICamera);
            }
            cameraList = newCameraList;
            currentCamera = cameraList[0];
        }
        #endregion File operations

        #region Member variables
        private List<ICamera> cameraList = new List<ICamera>();
        ICamera currentCamera;
        #endregion

    }
}
